package com.cr.attach.service.impl;

import cn.hutool.core.util.StrUtil;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.model.ObjectMetadata;
import com.aliyun.oss.model.PutObjectResult;
import com.cr.attach.config.OSSConfig;
import com.cr.attach.service.IAttachService;
import com.cr.common.exception.ServiceException;
import com.cr.common.response.ServiceCode;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Service
@Slf4j
public class AttachServiceImpl implements IAttachService {

    @Value("${app.upload.path}")
    private String uploadPath;

    @Value("${app.upload.url-prefix}")
    private String urlPrefix;

    @Autowired
    private OSSConfig ossConfig;

    private static final Map<String, String> CONTENT_TYPE_MAPPING = new HashMap<>();

    static {
        CONTENT_TYPE_MAPPING.put(".jpg", "image/jpg");
        CONTENT_TYPE_MAPPING.put(".jpeg", "image/jpg");
        CONTENT_TYPE_MAPPING.put(".png", "image/jpg");
        CONTENT_TYPE_MAPPING.put(".gif", "image/gif");
        CONTENT_TYPE_MAPPING.put(".bmp", "image/bmp");
    }
    @Override
    public String upload(MultipartFile multipartFile) {
        //创建OSS对象
        OSS ossClient = new OSSClientBuilder().build(
                ossConfig.getEndpoint(), ossConfig.getAccessKeyId(),
                ossConfig.getAccessKeySecret());
        //获取原文件名
        String originalFilename = multipartFile.getOriginalFilename();

        //获取文件后缀
        int lastIndexOf;
        if (originalFilename == null || (lastIndexOf =
                originalFilename.lastIndexOf(".")) == -1) {
            throw new ServiceException(ServiceCode.ERROR_UPLOAD_INVALID_TYPE, "上传的文件类型有误！");
        }
        String ext = originalFilename.substring(lastIndexOf).toLowerCase();

        //获取内容类型
        String contentType = CONTENT_TYPE_MAPPING.get(ext);
        if (contentType == null) {
            throw new ServiceException(ServiceCode.ERROR_UPLOAD_INVALID_TYPE, "上传的文件类型有误！");
        }
        //拼装OSS上存储的路径
        String folder = DateTimeFormatter.ofPattern("yyyy/MM/dd/").format(LocalDateTime.now());
        String fileName = UUID.randomUUID().toString().replace("-", "");

        //在OSS上bucket下的文件名：文件夹/文件名.后缀
        String uploadFileName = folder + fileName + ext;

        try{
            ObjectMetadata objectMetadata = new ObjectMetadata();
            objectMetadata.setContentType(contentType);

            PutObjectResult result = ossClient.putObject(
                    ossConfig.getBucketName(), uploadFileName,
                    multipartFile.getInputStream(), objectMetadata);

            if (result == null){
                throw new ServiceException(ServiceCode.ERROR_UNKNOWN, "上传文件失败，请稍后再试！");
            }
            //拼接OSS完整访问路径并返回
            return new StringBuilder()
                    .append("https://")
                    .append(ossConfig.getBucketName())
                    .append(".")
                    .append(ossConfig.getEndpoint())
                    .append("/")
                    .append(uploadFileName)
                    .toString();

        } catch (Exception e){
            log.error("文件上传失败：{}", e.getMessage());
            throw new ServiceException(ServiceCode.ERROR_UNKNOWN, "上传文件失败，请稍后再 试！");
        } finally {
            //关闭OSS服务，释放资源
            ossClient.shutdown();
        }





    }


    @Override
    public void deleteByUrl(String url) {
        if (StrUtil.isEmpty(url)) {
            throw new ServiceException("url不能为空");
        }
        String filePath = url.replace(urlPrefix, "");
        File file = new File(uploadPath, filePath);
        if (file.exists() && !file.delete()) {
            throw new ServiceException("删除图片失败");
        }
    }

}
